import {Component, OnInit, Output, EventEmitter} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {MAP_CONFIG} from '../map/mapconfig';
import Map from 'ol/Map';
import View from 'ol/View';
import Feature from 'ol/Feature';
import TileGrid from 'ol/tilegrid/TileGrid';
import Tile from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import HeatMap from 'ol/layer/Heatmap';
import XYZ from 'ol/source/XYZ';
import TileImage from 'ol/source/TileImage';
import Style from 'ol/style/Style';
import Icon from 'ol/style/Icon';
import Fill from 'ol/style/Fill';
import Circle from 'ol/style/Circle';
import Stroke from 'ol/style/Stroke';
import Text from 'ol/style/Text';
import Point from 'ol/geom/Point';
import LineString from 'ol/geom/LineString';
import Zoom from 'ol/control/Zoom';
import * as _ol_control_ from 'ol/control';
import * as _ol_interaction_ from 'ol/interaction';
import * as _ol_proj_ from 'ol/proj';
import Projection from 'ol/proj/Projection';
import * as _ol_extent_ from 'ol/extent';
// import SymbolUtils from 'SymbolUtils';
import VectorSource from 'ol/source/Vector.js';
import GeoJSON from 'ol/format/GeoJSON.js';

@Component({
  selector: 'qk-map',
  templateUrl: 'qkmap.component.html',
  styleUrls: ['qkmap.component.scss'],
  providers: []
})
export class QkMapComponent implements OnInit {
  public mapcore;
  private selectLocationHandler;
  private selectLocationLayer;
  private mapClickHandler;
  @Output()
  private outer = new EventEmitter();

  constructor(private http: HttpClient) {
  }

  public ngOnInit() {
    let tileExtent = MAP_CONFIG.mapExtent.split(',');
    let projectionName = 'EPSG:' + MAP_CONFIG.spatialRef;
    let projection = _ol_proj_.get(projectionName);
    if (!projection) {
      let units = 'm';
      projection = new Projection({code: 'urn:ogc:def:crs:EPSG::' + MAP_CONFIG.spatialRef, units: units});
      _ol_proj_.addProjection(projection);
      projection = new Projection({code: projectionName, units: units});
      _ol_proj_.addProjection(projection);
    }
    this.mapcore = new Map({
      target: 'dom_map',
      view: new View({
        center: [(Number(tileExtent[0]) + Number(tileExtent[2])) / 2, (Number(tileExtent[1]) + Number(tileExtent[3])) / 2],
        minZoom: 0,
        maxZoom: MAP_CONFIG.maxZoom,
        projection: projection
      }),
      controls: _ol_control_.defaults(),
      interactions: _ol_interaction_.defaults({altShiftDragRotate: false, pinchRotate: false})
    });
    // 添加栅格瓦片图层
    if (MAP_CONFIG.tileLayers) {
      for (let i = 0; i < MAP_CONFIG.tileLayers.length; i++) {
        let layerInfo: any = MAP_CONFIG.tileLayers[i];
        let layer: any;
        if (MAP_CONFIG.tileLayers[i].mapServerType === 1) {
          layer = this.createXYZTileLayer(layerInfo);
        } else if (MAP_CONFIG.tileLayers[i].mapServerType === 4) {
          layer = this.createBaiduTileLayer(layerInfo);
        }
        this.mapcore.addLayer(layer);
      }
    }
    // 添加矢量图层
    if (MAP_CONFIG.vectorLayers) {
      for (let i = 0; i < MAP_CONFIG.vectorLayers.length; i++) {
        let layerInfo: any = MAP_CONFIG.vectorLayers[i];
        let layer: any;
        layer = this.createVectorLayer(layerInfo);
        this.mapcore.addLayer(layer);
      }
    }
    this.mapcore.getView().fit(tileExtent, this.mapcore.getSize());
    let zoom = new Zoom();
    this.mapcore.addControl(zoom);
      // this.startSelectLocation(function (e) {
      // });

    // this.humanSelect(function (points) {
    // });
    // this.sendData();
  }

  public createVectorLayer(layerInfo: any) {
    let style = new Style({
      fill: new Fill({
        color: 'rgba(5, 29, 82, 0.6)'
      }),
      stroke: new Stroke({
        color: 'rgba(255, 255, 255, 0.6)',
        width: 1
      }),
      text: new Text({fill: new Fill({color: '#ffffff'})})
    });

    return new VectorLayer({
      renderMode: 'image',
      source: new VectorSource({
        url: layerInfo.mapServerUrl,
        format: new GeoJSON()
      }),
      style: function (feature) {
        style.getText().setText(feature.get('name'));
        return style;
      }
    });
  }

  public createXYZTileLayer(layerInfo: any) {
    // 获取地图范围
    let tileExtent = layerInfo.tile.mapExtent.split(',');
    tileExtent = tileExtent.map(s => +s);
    // 获取地图分辨率
    let resolutions = layerInfo.tile.mapResolution.split(',');
    resolutions = resolutions.map(s => +s);

    let tileGrid = new TileGrid({
      extent: tileExtent,
      resolutions: resolutions.reverse(),
      origin: [layerInfo.tile.origionPtX, layerInfo.tile.origionPtY],
      tileSize: layerInfo.tile.tileSize
    });

    let serviceUrl = layerInfo.mapServerUrl;

    let projectionName = 'EPSG:' + layerInfo.tile.spatialRef;
    let projection = _ol_proj_.get(projectionName);
    if (!projection) {
      let units = 'm';
      projection = new Projection({code: 'urn:ogc:def:crs:EPSG::' + MAP_CONFIG.tile.spatialRef, units: units});
      _ol_proj_.addProjection(projection);
      projection = new Projection({code: projectionName, units: units});
      _ol_proj_.addProjection(projection);
    }
    let that = this;
    return new Tile({
      source: new XYZ({
        tileGrid: tileGrid,
        projection: projection,
        tileUrlFunction: function (tileCoord) {
          let x = tileCoord[1].toString();
          let y = (-tileCoord[2] - 1).toString();
          let z = tileCoord[0].toString();
          if (layerInfo.tileType === 1) {
            x = 'C' + that.zeroFill(tileCoord[1], 8, 16);
            y = 'R' + that.zeroFill(-tileCoord[2] - 1, 8, 16);
            z = 'L' + that.zeroFill(tileCoord[0], 2, 10);
          }
          let url = serviceUrl.replace(/{z}/g, z)
            .replace('{x}', x)
            .replace('{y}', y);
          return url;
        },
        url: layerInfo.mapServerUrl
      })
    });
  }

  // 给8位字符串文件名补0
  private zeroFill(num, len, radix) {
    let str = num.toString(radix || 10);
    while (str.length < len) {
      str = '0' + str;
    }
    return str;
  }

  private createBaiduTileLayer(layerInfo: any) {
    let projection = _ol_proj_.get('EPSG:3857');
    let resolutions = [];
    for (let i = 0; i < 20; i++) {
      resolutions[i] = Math.pow(2, 18 - i);
    }
    let tileGrid = new TileGrid({
      origin: [0, 0],
      resolutions: resolutions
    });
    let baidu_source = new TileImage({
      projection: projection,
      tileGrid: tileGrid,
      tilePixelRatio: 1, // 在高分辨率设备上必须设置此项
      tileUrlFunction: function (tileCoord, pixelRatio, proj) {
        if (!tileCoord) {
          return '';
        }
        let z = tileCoord[0];
        let x = tileCoord[1];
        let y = tileCoord[2];

        if (x < 0) {
          x = 'M' + (-x);
        }
        if (y < 0) {
          y = 'M' + (-y);
        }
        return layerInfo.mapServerUrl.replace(/{z}/g, z)
          .replace('{x}', x)
          .replace('{y}', y);
      }
    });

    return new Tile({
      source: baidu_source
    });
  }

  //
  // private initTiandituTile(id) {
  //   //获取地图中心点
  //   let mapInitPos = this.mapConfig.mapInitPos.split(",");
  //   mapInitPos = mapInitPos.map(s => +s);
  //   //获取地图范围
  //   let tileExtent = this.mapConfig.mapExtent.split(",");
  //   tileExtent = tileExtent.map(s => +s);
  //   //获取地图分辨率
  //   let resolutions = this.mapConfig.mapResolution.split(",");
  //   resolutions = resolutions.map(s => +s);
  //
  //   let view = {};
  //   if (mapInitPos.length >= 2) {
  //     view = new View({
  //       center: [mapInitPos[0], mapInitPos[1]],
  //       projection: _ol_proj_.get('EPSG:4326'),
  //       // zoom: mapInitPos[2]
  //       zoom: 11
  //     });
  //   } else {
  //     view = new View({
  //       extent: tileExtent,
  //       projection: _ol_proj_.get('EPSG:4326'),
  //       resolutions: resolutions.reverse()
  //     });
  //   }
  //
  //   this.mapcore = new Map({
  //     target: id,
  //     layers: [
  //       new Tile({
  //         source: new XYZ({
  //           title: "天地图路网",
  //           url: "http://t" + Math.round(Math.random() * 7) + ".tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}"
  //         })
  //       }),
  //       new Tile({
  //         source: new XYZ({
  //           title: "天地图文字标注",
  //           url: "http://t" + Math.round(Math.random() * 7) + ".tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}"
  //         })
  //       })
  //     ],
  //     controls: _ol_control_.defaults({ rotate: false }),
  //     view: view
  //   });
  //   if (mapInitPos.length < 2) {
  //     this.mapcore.getView().fit(tileExtent, this.mapcore.getSize());
  //   }
  //   let zoom = new Zoom();
  //   this.mapcore.addControl(zoom);
  // }
  public addVectorLayer(layerID) {
    let vectorSource = new VectorSource({
      features: []
    });
    let vectorLayer = new VectorLayer({
      source: vectorSource
    });
    vectorLayer.set('layerID', layerID);
    this.mapcore.addLayer(vectorLayer);
    return vectorLayer;
  }

  // /**热力图 */
  // public addHeatMapLayer(layerID) {
  //   let vectorSource = new VectorSource({
  //     features: []
  //   });
  //   let heatMapLayer = new HeatMap({
  //     source: vectorSource,
  //     blur: 15,
  //     radius: 8
  //   });
  //   heatMapLayer.set("layerID", layerID);
  //   this.mapcore.addLayer(heatMapLayer);
  //   return heatMapLayer;
  // }
  /**定位 */
  public addPoints(vectorLayer, points) {
    for (let i = 0; i < points.length; i++) {
      let feature = new Feature({
        geometry: new Point([points[i].geometry.x, points[i].geometry.y]),
      });
      if (points[i].attr) {
        feature.setProperties(points[i].attr);
      }
      let iconStyles = [];
      if (points[i].style.styleType === 1) { // 叠加人员头像的定位图标
        let style = new Style({
          image: new Icon({
            anchor: [0.5, 64],
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            src: 'image/location.svg'
          })
        });
        iconStyles.push(style);
        if (points[i].style.humanIconUrl) {
          let headStyle = new Style({
            image: new Icon({
              anchor: [0.5, 170],
              anchorXUnits: 'fraction',
              anchorYUnits: 'pixels',
              src: points[i].style.humanIconUrl,
              scale: 0.3
            })
          });
          iconStyles.push(headStyle);
        }
        feature.setStyle(iconStyles);
        vectorLayer.getSource().addFeature(feature);
      } else if (points[i].style.styleType === 2) {
        let style = new Style({
          image: new Circle({
            radius: points[i].style.radius,
            fill: new Fill({
              color: points[i].style.fillColor
            })
          })
        });
        iconStyles.push(style);
        let locStyle = new Style({
          image: new Icon({
            anchor: [0.5, 30],
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            src: points[i].style.iconUrl
          })
        });
        iconStyles.push(locStyle);
        feature.setStyle(iconStyles);
        vectorLayer.getSource().addFeature(feature);
      } else if (points[i].style.styleType === 3) {
        let style = new Style({
          image: new Icon({
            anchor: [0.5, 40],
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            src: 'image/patrol.png'
          })
        });
        feature.setStyle(style);
        vectorLayer.getSource().addFeature(feature);
      } else if (points[i].style.styleType === 4) {
        // this.addPatrolPoints(vectorLayer, feature, points[i].attr.N);
      } else if (points[i].style.styleType === 5) { // 轨迹起点和终点样式
        let onterStyle = new Style({
          image: new Circle({
            radius: points[i].style.radius * 5,
            fill: new Fill({
              color: points[i].style.backColor
            })
          })
        });
        let midStyle = new Style({
          image: new Circle({
            radius: points[i].style.radius * 1.5,
            fill: new Fill({
              color: 'white'
            })
          })
        });
        let innerStyle = new Style({
          image: new Circle({
            radius: points[i].style.radius,
            fill: new Fill({
              color: points[i].style.fillColor
            })
          })
        });
        iconStyles.push(onterStyle);
        iconStyles.push(midStyle);
        iconStyles.push(innerStyle);
        feature.setStyle(iconStyles);
        vectorLayer.getSource().addFeature(feature);
      }
    }
  }

  //
  // public addHeatMapPoints(heatMapLayer, points) {
  //   let features = [];
  //   for (let i = 0; i < points.length; i++) {
  //     let feature = new Feature({
  //       geometry: new Point([points[i].geometry.x, points[i].geometry.y])
  //     });
  //     features.push(feature);
  //   }
  //   heatMapLayer.getSource().addFeatures(features);
  // }
  //
  // public addLineString(vectorLayer, lineString) {
  //   let feature = new Feature({
  //     geometry: new LineString(lineString.geometry)
  //   });
  //   feature.setStyle(new Style({
  //     stroke: new Stroke({
  //       width: lineString.style.width,
  //       color: lineString.style.color
  //     })
  //   }));
  //   vectorLayer.getSource().addFeature(feature);
  //   return feature;
  // }
  //
  // public drawTrack(vectorLayer, trackList) {
  //   let pointGeometries = [];
  //   let pointFeatures = [];
  //   // 起点和终点要素
  //   let startPointFeature = {
  //     geometry: { "x": trackList[0].X, "y": trackList[0].Y },
  //     attr: trackList[0],
  //     style: { styleType: 5, fillColor: [30, 144, 255, 1], backColor: [30, 144, 255, 0.2], radius: 8 }
  //   };
  //   pointFeatures.push(startPointFeature);
  //   let length = trackList.length;
  //   let endPointFeature = {
  //     geometry: { "x": trackList[length - 1].X, "y": trackList[length - 1].Y },
  //     attr: trackList[length - 1],
  //     style: { styleType: 5, fillColor: [148, 0, 211, 1], backColor: [148, 0, 211, 0.2], radius: 8 }
  //   };
  //   pointFeatures.push(endPointFeature);
  //   // 轨迹线要素
  //   for (let i = 0; i < trackList.length; i++) {
  //     pointGeometries.push([trackList[i].X, trackList[i].Y]);
  //   }
  //   let lineString = {
  //     geometry: pointGeometries,
  //     attr: "",
  //     style: { width: 6, color: [30, 144, 255, 1] }
  //   };
  //   // 渲染轨迹
  //   this.addPoints(vectorLayer, pointFeatures);
  //   let feature = this.addLineString(vectorLayer, lineString);
  //   this.mapcore.getView().fit(feature.getGeometry());
  // }
  //
  // public getPointsExtent(points) {
  //   let minX = points[0].geometry.x;
  //   let minY = points[0].geometry.y;
  //   let maxX = points[0].geometry.x;
  //   let maxY = points[0].geometry.y;
  //   for (let i = 1; i < points.length; i++) {
  //     if (minX > points[i].geometry.x) {
  //       minX = points[i].geometry.x
  //     }
  //     if (minY > points[i].geometry.y) {
  //       minY = points[i].geometry.y
  //     }
  //     if (maxX < points[i].geometry.x) {
  //       maxX = points[i].geometry.x
  //     }
  //     if (maxY < points[i].geometry.y) {
  //       maxY = points[i].geometry.y
  //     }
  //   }
  //   return [minX, minY, maxX, maxY];
  // }
  /**范围*/
  public fitExtent(extent) {
    if (extent[0] === extent[2] && extent[1] === extent[3]) {
      this.mapcore.getView().fit([extent[0] - 500, extent[1] - 500, extent[2] + 500, extent[3] + 500]);
    } else {
      this.mapcore.getView().fit(extent);
    }
  }

  // /**级别 */
  // public zoomTo(zoom) {
  //   this.mapcore.getView().animate({ zoom: zoom });
  // }

  public startSelectLocation(callback) {
    let that = this;
    // 添加选择地址图层
    this.selectLocationLayer = this.addVectorLayer('selectLocationLayer');
    this.selectLocationHandler = function (evt) {
      that.selectLocationLayer.getSource().clear();
      let point = {
        geometry: {x: evt.coordinate[0], y: evt.coordinate[1]},
        style: {styleType: 2, radius: 5, fillColor: '#ff0000', iconUrl: '/assets/images/location.png'}
      };
      that.addPoints(that.selectLocationLayer, [point]);
      callback(evt);
    };
    this.mapcore.on('singleclick', this.selectLocationHandler);
  }

  public endSelectLocation() {
    this.mapcore.removeLayer(this.selectLocationLayer);
    this.mapcore.un('singleclick', this.selectLocationHandler);
  }

    public addMapClickEvent(context , callback) {
        let that = this;
        this.mapClickHandler = function (evt) {
            let coordinate = evt.coordinate;
            let features = that.mapcore.getFeaturesAtPixel(evt.pixel);
            callback(context, {'coordinate': coordinate, 'features' : features});
        }
        this.mapcore.on('click', this.mapClickHandler);
    }
    public removeMapClickEvent() {
        this.mapcore.un('click', this.mapClickHandler);
    }
}
